import java.io.*;
import java.util.*;

/** <p>An Event object need * a date, * a band's name, * a band's MySpace URL,
 * * a location/pub, * a location's web-site URL (or empty) and * a city.</p>
 * <p>It have three constructors which differentiate only for the date format:
 * like text "yyyy/MM/dd-HH:mm:ss" (and variances) or directly like a GregorianCalendar or a Date object.</p> **/
public class Event implements java.io.Serializable {

/*~~~~ ATTRIBUTES ~~~~*/

	private static final long serialVersionUID = 1L;
	public static final String nl = Character.toString((char)13) + Character.toString((char)10);
	public static final String nlnn = Character.toString((char)13) + "\n";
	protected GregorianCalendar gcalWhen = null; //Date
	protected String strWho; //band
	protected String urlWho; //band myspace link
	protected String strWhat; //event name
	protected String urlWhat; //event website
	protected String strWhere; //city + district 


/*~~~~ CONSTRUCTORS ~~~~*/

	/** This is an internal only constructor, used by other constructors. **/
	protected Event(String strWho, String urlWho, String strWhat, String urlWhat, String strWhere) {
		this.strWho = strWho;
		this.urlWho = urlWho;
		this.strWhat = strWhat;
		this.urlWhat = urlWhat;
		this.strWhere = strWhere;
	}

	/** To create an Event object from an ArrayList. **/ 
	public Event(ArrayList<String> strInfo) {
		this(strInfo.get(0), strInfo.get(1), strInfo.get(5), strInfo.get(4), strInfo.get(6));
		/*temp/System.out.println("strWho: " + strInfo.get(0) + ", urlWho: " + strInfo.get(1) + ", strDate: " + strInfo.get(2) + ", strTime: " + strInfo.get(3) + ", strWhat: " + strInfo.get(5)+ ", urlWhat: " + strInfo.get(4) + ", strWhere: " + strInfo.get(6) + "\n");/*temp*/
		makeDataArray(strInfo);
	}

	/** <p>To create an event you need following arguments:<br />
	 * <ul>
	 * <li> a GregorianCalendar object with the date and hour of the event;</li>
	 * <li> a String with the name of the band;</li>
	 * <li> a String with the myspace link for the band;</li>
	 * <li> a String with the name of the location/pub where is the event;</li>
	 * <li> a String with the link to the location's website (or empty string "");</li>
	 * <li> a String with the city (you can add district, too, if needed).</li>
	 * </ul></p> **/
	public Event(GregorianCalendar gcalWhen, String strWho, String urlWho,
			String strWhat, String urlWhat, String strWhere) {
		this(strWho, urlWho, strWhat, urlWhat, strWhere);
		this.gcalWhen = gcalWhen;
	}

	/** <p>To create an event you need following arguments:<br />
	 * <ul>
	 * <li> a Date object with the date and hour of the event;</li>
	 * <li> a String with the name of the band;</li>
	 * <li> a String with the myspace link for the band;</li>
	 * <li> a String with the name of the location/pub where is the event;</li>
	 * <li> a String with the link to the location's website (or empty string "");</li>
	 * <li> a String with the city (you can add district, too, if needed).</li>
	 * </ul></p> **/
	public Event(Date dateWhen, String strWho, String urlWho,
			String strWhat, String urlWhat, String strWhere) {
		this(strWho, urlWho, strWhat, urlWhat, strWhere);

		this.gcalWhen = new GregorianCalendar();
		this.gcalWhen.setTime(dateWhen);
	}

	/** <p>To create an event you need following arguments:<br />
	 * <ul>
	 * <li> a String with the date and hour of the event in following formats:<br />
	 * - &nbsp;&nbsp;&nbsp;<code>empty</code> [or < 10 chars] for current time;<br />
	 * - &nbsp;&nbsp;&nbsp;<code>yyyy/MM/dd</code> [or < 16 chars] for <code>year</code>, <code>month</code> and <code>day</code> at midnight;<br />
	 * - &nbsp;&nbsp;&nbsp;<code>yyyy/MM/dd-HH:mm</code> [or < 19 chars] for <code>year</code>, <code>month</code> and <code>day</code> with <code>hours</code> and <code>minutes</code>;<br />
	 * - &nbsp;&nbsp;&nbsp;<code>yyyy/MM/dd-HH:mm:ss</code> [or > 19 chars] for <code>year</code>, <code>month</code> and <code>day</code> with <code>hours</code>, <code>minutes</code> and <code>seconds</code>;
	 * <li> a String with the name of the band;</li>
	 * <li> a String with the myspace link for the band;</li>
	 * <li> a String with the name of the location/pub where is the event;</li>
	 * <li> a String with the link to the location's website (or empty string "");</li>
	 * <li> a String with the city (you can add district, too, if needed).</li>
	 * </ul></p> **/
	public Event(String strWhen, String strWho, String urlWho,
			String strWhat, String urlWhat, String strWhere) {
		this(strWho, urlWho, strWhat, urlWhat, strWhere);
		int intYear = -1, intMonth = -1, intDay = -1, intHour = -1, intMin = -1, intSec = -1; 
		if(strWhen.length() > 3) intYear = Integer.parseInt(numberize(strWhen.substring(0,4)));
		if(strWhen.length() > 6) intMonth = Integer.parseInt(numberize(strWhen.substring(5,7))) - 1;
		if(strWhen.length() > 9) intDay = Integer.parseInt(numberize(strWhen.substring(8,10)));
		if(strWhen.length() > 12) intHour = Integer.parseInt(numberize(strWhen.substring(11,13)));
		if(strWhen.length() > 15) intMin = Integer.parseInt(numberize(strWhen.substring(14,16)));
		if(strWhen.length() > 18) intSec = Integer.parseInt(numberize(strWhen.substring(17,19)));

		if(intDay == -1) this.gcalWhen = new GregorianCalendar();
		else if(intMin == -1) this.gcalWhen = new GregorianCalendar(intYear, intMonth, intDay);
		else if(intSec == -1) this.gcalWhen = new GregorianCalendar(intYear, intMonth, intDay, intHour, intMin);
		else this.gcalWhen = new GregorianCalendar(intYear, intMonth, intDay, intHour, intMin, intSec);
	}


/*~~~~ PUBLIC METHODS ~~~~*/

	public String getStrWhen() {
		String strDay, strMonth, strHour, strMins;

		strDay = EventsManager.strFormat(Integer.toString(gcalWhen.get(Calendar.DAY_OF_MONTH)), 2);
		strMonth = EventsManager.strFormat(Integer.toString(gcalWhen.get(Calendar.MONTH) + 1), 2);
		strHour = EventsManager.strFormat(Integer.toString(gcalWhen.get(Calendar.HOUR_OF_DAY)), 2);
		strMins = EventsManager.strFormat(Integer.toString(gcalWhen.get(Calendar.MINUTE)), 2);

		return  strDay + "/" + strMonth + "/" + gcalWhen.get(Calendar.YEAR) + " " + strHour + ":" + strMins;
	}


	public Event clone(){
		return new Event(gcalWhen, strWho, urlWho, strWhat, urlWhat, strWhere);
	}


	public void saveOnFile(String fileName, boolean blnAppend) throws IOException{
		BufferedWriter objBufferWrite = new BufferedWriter(new FileWriter(fileName, blnAppend));
		objBufferWrite.write(toString().replace("\n", nlnn) + nlnn + nlnn);
		objBufferWrite.flush();
		objBufferWrite.close();
	}

	public void saveOnFile(String fileName) throws IOException{
		saveOnFile(fileName, false);
	}


	/** <p>Return the event's informations:
	 * <ul>
	 * <li>if <code>blnSingleLine</code> is <code>true</code>, information will be forced in a single line;</li>
	 * <li>if <code>blnSingleLine</code> is <code>false</code>, information will be formatted in multiple lines.</li>
	 * </ul></p> **/
	public String toString(boolean blnSingleLine) {
		if (blnSingleLine)
			return "~ EVENT DETAILS => Band: \"" + strWho + "\" -> " + urlWho + " "
			+ ", date: \"" + getStrWhen() + "\""
			+ ", location: \"" + strWhat + "\" -> " + urlWhat + " "
			+ ", city: \"" + strWhere + "\"";
		else
			return "~~~~~ EVENT DETAILS ~~~~~"
			+ "\nBand           : \"" + strWho + "\""
			+ "\nBand's link    : \"" + urlWho + "\""
			+ "\nDate & time    : \"" + getStrWhen() + "\""
			+ "\nLocation       : \"" + strWhat + "\""
			+ "\nLocation's link: \"" + urlWhat + "\""
			+ "\nCity           : \"" + strWhere + "\"";
	}

	/** <p>Return the event's informations formatted in multiple lines.</p> **/
	public String toString() {
		return toString(false);
	}

/*~~~~ STATIC METHODS ~~~~*/

	/** <p>This method delete all non-numerical characters from a string</p>
	 *  <p>Other than numbers, accepts only a <code>minus</code> [-], if found for first,
	 *  and first <code>dot</code> [.] ever found. **/
	public static String numberize(String strOrig){
		return EventsManager.numberize(strOrig);
	}


	public void makeDataArray(ArrayList<String> strInfo){
		String[] splitData = strInfo.get(2).split(" ");
		int year = Integer.parseInt(splitData[2]);
		int month = 0;

		switch (Enummonth.valueOf(splitData[1])) {
			case gen: case jan:
				month = 0;
				break;
			case feb:
				month = 1;
				break;
			case mar:
				month = 2;
				break;
			case apr:
				month = 3;
				break;
			case mag: case may:
				month = 4;
				break;
			case giu: case jun:
				month = 5;
				break;
			case lug: case jul:
				month = 6;
				break;
			case ago: case aug:
				month = 7;
				break;
			case set: case sep:
				month = 8;
				break;
			case ott: case oct:
				month = 9;
				break;
			case nov:
				month = 10;
				break;
			case dic: case dec:
				month = 11;
				break;
			default:
				month = 0;
				break;
		}

		int day = Integer.parseInt(splitData[0]);
		String[] splitOra = strInfo.get(3).split("\\.");
		int hourOfDay = Integer.parseInt(splitOra[0]);
		int minute = Integer.parseInt(splitOra[1]);
		this.gcalWhen = new GregorianCalendar(year, month, day, hourOfDay, minute);
	}

	public enum Enummonth{
		gen, jan,
		feb,
		mar,
		apr,
		mag, may,
		giu, jun,
		lug, jul,
		ago, aug,
		set, sep,
		ott, oct,
		nov,
		dic, dec;
	}

/*~~~~ GET METHODS ~~~~*/

	public GregorianCalendar getGcalWhen() {
		return gcalWhen;
	}

	public String getStrWho() {
		return strWho;
	}

	public String getUrlWho() {
		return urlWho;
	}

	public String getStrWhat() {
		return strWhat;
	}

	public String getUrlWhat() {
		return urlWhat;
	}

	public String getStrWhere() {
		return strWhere;
	}


/*~~~~ SET METHODS ~~~~*/

	public void setGcalWhen(GregorianCalendar gcalWhen) {
		this.gcalWhen = gcalWhen;
	}

	public void setStrWho(String strWho) {
		this.strWho = strWho;
	}

	public void setUrlWho(String urlWho) {
		this.urlWho = urlWho;
	}

	public void setStrWhat(String strWhat) {
		this.strWhat = strWhat;
	}

	public void setUrlWhat(String urlWhat) {
		this.urlWhat = urlWhat;
	}

	public void setStrWhere(String strWhere) {
		this.strWhere = strWhere;
	}
}
